package com.networklib;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.networklib.http.exception.NetException;
import com.networklib.http.other.HttpMethod;
import com.networklib.task.TaskResultCode;
import com.networklib.task.reflect.TypeToken;
import com.networklib.task.WeakHandler;
import com.networklib.task.base.ATask;
import com.networklib.task.base.TaskService;
import com.networklib.task.exception.TaskException;
import com.networklib.task.impl.SimpleHttpTask;
import com.networklib.task.service.SimpleConcurrentService;

import java.io.IOException;
import java.util.Map;

public class Excuter {
    private InternalHandler innerHandler;
    private static Excuter excuter;

    public static Excuter getInstance() {
        if (excuter == null) {
            synchronized (Excuter.class) {
                if (excuter == null) {
                    excuter = new Excuter();
                }
            }
        }
        return excuter;
    }

    public <T> void postRequest(Context context, String url, final ExcuterCallback<T> excuterCallback, Map<String, Object> params) {
        try {
            SimpleHttpTask simpleHttpTask = new SimpleHttpTask(context, url, HttpMethod.POST, params);
            SimpleConcurrentService flowTaskService = new SimpleConcurrentService();
            flowTaskService.addTask(simpleHttpTask);
            flowTaskService.setTaskCallBack(new TaskService.TaskCallBack() {
                @Override
                public boolean before(TaskResult taskResult) {
                    return false;
                }

                @Override
                public void onComplete(TaskResult taskResult) {
                    try {
                        T result = taskResult.getResult(new TypeToken<T>() {
                        });
                        TaskResponse<T> taskResponse = new TaskResponse<T>(taskResult.getTag(), taskResult.getResultCode(), result);
                        getInnerHandler().obtainMessage(InternalHandler.WHAT_COMPLETE, new HandlerBean<T>(excuterCallback, taskResponse)).sendToTarget();
                    } catch (TaskException | IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void after(TaskResult taskResult) {

                }
            });
            flowTaskService.excute();
        } catch (NetException e) {
            e.printStackTrace();
        }
    }

    public <T> void getRequest(Context context, String url, final ExcuterCallback<T> excuterCallback, Map<String, Object> params) {
        try {
            SimpleHttpTask simpleHttpTask = new SimpleHttpTask(context, url, HttpMethod.GET, params);
            SimpleConcurrentService flowTaskService = new SimpleConcurrentService();
            flowTaskService.addTask(simpleHttpTask);
            flowTaskService.setTaskCallBack(new TaskService.TaskCallBack() {
                @Override
                public boolean before(TaskResult taskResult) {
                    return false;
                }

                @Override
                public void onComplete(TaskResult taskResult) {
                    try {
                        T result = taskResult.getResult(new TypeToken<T>() {
                        });
                        TaskResponse<T> taskResponse = new TaskResponse<T>(taskResult.getTag(), taskResult.getResultCode(), result);
                        getInnerHandler().obtainMessage(InternalHandler.WHAT_COMPLETE, new HandlerBean<T>(excuterCallback, taskResponse)).sendToTarget();
                    } catch (TaskException | IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void after(TaskResult taskResult) {

                }
            });
            flowTaskService.excute();
        } catch (NetException e) {
            e.printStackTrace();
        }
    }


    protected Handler getInnerHandler() {
        if (innerHandler == null) {
            synchronized (ATask.class) {
                if (innerHandler == null) {
                    innerHandler = new InternalHandler(this);
                }
            }
        }
        return innerHandler;
    }

    public interface ExcuterCallback<T> {
        void onCall(TaskResponse<T> taskResponse);
    }

    private static class HandlerBean<T> {
        ExcuterCallback<T> excuterCallback;
        TaskResponse<T> taskResponse;

        public HandlerBean(ExcuterCallback<T> excuterCallback, TaskResponse<T> taskResponse) {
            this.excuterCallback = excuterCallback;
            this.taskResponse = taskResponse;
        }
    }

    public static class TaskResponse<T> {
        private final String tag;
        private TaskResultCode resultCode;
        private T result;

        public TaskResponse(String tag, TaskResultCode resultCode, T result) {
            this.tag = tag;
            this.resultCode = resultCode;
            this.result = result;
        }

        public String getTag() {
            return tag;
        }

        public TaskResultCode getResultCode() {
            return resultCode;
        }

        public void setResultCode(TaskResultCode resultCode) {
            this.resultCode = resultCode;
        }

        public T getResult() {
            return result;
        }

        public void setResult(T result) {
            this.result = result;
        }
    }


    private static class InternalHandler extends WeakHandler<Excuter> {
        public static final int WHAT_COMPLETE = 11;

        public InternalHandler(Excuter owner) {
            super(Looper.getMainLooper(), owner);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case WHAT_COMPLETE:
                    HandlerBean handlerBean = (HandlerBean) msg.obj;
                    handlerBean.excuterCallback.onCall(handlerBean.taskResponse);
                    break;
            }
        }
    }

}
